package dsx.netServer;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import dsx.cache.DsxByteBuffer;
import dsx.console.DsxConsole;
import dsx.inf.IDataTransfer;
import dsx.inf.ISlicer;
import dsx.log.ServLog;

class TCPChannelHandler extends ChannelInboundHandlerAdapter {
	// 变量
	IDataTransfer dataTransfer = null;
	ISlicer slicer = null;

	_TCPConfig config = null;
	TCPChannelTable channelTable = null;
	int lastCommTime;
	Object timerLock;
	DsxByteBuffer recvBuf = null;
	// 属性
	int channelId = -1;

	public int getChannelId() {
		return channelId;
	}

	public void setChannelId(int channelId) {
		this.channelId = channelId;
	}

	private ChannelHandlerContext ctx = null;

	public ChannelHandlerContext getCtx() {
		return ctx;
	}

	public void setCtx(ChannelHandlerContext ctx) {
		this.ctx = ctx;
	}

	public TCPChannelHandler(IDataTransfer dataTransfer, ISlicer slicer,
			_TCPConfig config, TCPChannelTable channelTable) {
		this.dataTransfer = dataTransfer;
		this.slicer = slicer;
		this.config = config;
		this.channelTable = channelTable;
		this.timerLock = new Object();
		refreshLastCommTime();
	}

	private void refreshLastCommTime() {
		synchronized (this.timerLock) {
			this.lastCommTime = this.channelTable.getTick();
		}
	}

	public int getLastCommTime() {
		synchronized (this.timerLock) {
			return this.lastCommTime;
		}
	}

	public void close() {
		try {
			this.ctx.close();
		} catch (Exception ex) {
			DsxConsole.out(ex.getMessage(), "net server handler removed",
					ServLog.error);
			throw ex;
		}
	}

	@Override
	public void handlerAdded(ChannelHandlerContext ctx) {
		try {
			if (!this.channelTable.add(this)) {
				DsxConsole.out(" fail add to talbe", "net server handler added",
						ServLog.info);
				try {
					ctx.close();
				} catch (Exception ex) {
					DsxConsole.out(ex.getMessage(), "net server handler added 1",
							ServLog.error);
				}
				return;
			}
			this.recvBuf = new DsxByteBuffer(this.config.getInitBufSize(),
					this.config.getMaxBufSize());
			this.ctx = ctx;
			refreshLastCommTime();
		} catch (Exception ex) {
			DsxConsole.out(ex.getMessage(), "net server handler added 2",
					ServLog.error);
			throw ex;
		}
	}

	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) {
		try {
			if (this.channelTable != null)
				this.channelTable.remove(this);
			this.recvBuf.clear();
			this.recvBuf = null;
		} catch (Exception ex) {
			DsxConsole.out(ex.getMessage(), "net server handler removed",
					ServLog.error);
			throw ex;
		}
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception { // (2)
		if (msg != null) {
			ByteBuf in = (ByteBuf) msg;
			try {
				refreshLastCommTime();
				if (this.dataTransfer == null || this.slicer == null
						|| this.channelId < 0)
					return;
				while (in.readableBytes() > 0) {
					this.recvBuf.put(in.readByte());
				}
				in.discardReadBytes();
				while (this.recvBuf.readable()) {
					byte[] req = slicer.slice(this.recvBuf);
					if (req == null)
						break;
					this.dataTransfer.recv(ctx, req);
				}
			} catch (Exception ex) {
				DsxConsole.out(ex.getMessage(), "net server channel read",
						ServLog.error);
				throw ex;
			} finally {
				in.release();
			}
		} else {
			DsxConsole.out("msg is null", "net server channel read",
					ServLog.error);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		DsxConsole.out(cause.getMessage(), "net server", ServLog.error);
		try {
			ctx.close();
		} catch (Exception ex) {
		}
	}

}
